// 在 N * N 的网格上，我们放置一些 1 * 1 * 1  的立方体。

// 每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。

// 请你返回最终形体的表面积。

 




// 示例 1：

// 输入：[[2]]
// 输出：10


// 示例 2：

// 输入：[[1,2],[3,4]]
// 输出：34


// 示例 3：

// 输入：[[1,0],[0,2]]
// 输出：16


// 示例 4：

// 输入：[[1,1,1],[1,0,1],[1,1,1]]
// 输出：32


// 示例 5：

// 输入：[[2,2,2],[2,1,2],[2,2,2]]
// 输出：46


 

// 提示：


// 	1 <= N <= 50
// 	0 <= grid[i][j] <= 50

#include <vector>

using namespace std;

// 从 (0,0) 位置开始累加，先根据 grid[0][0] 的值算出若仅有该位置的三维物体的表面积，
// 然后向 (0,1) 位置遍历，同样要先根据 grid[0][1] 的值算出若仅有该位置的三维物体的表面积，
// 跟之前 grid[0][0] 的累加，然后再减去遮挡住的面积，通过 max(grid[0][0],grid[0][1])x2 来得到，
// 这样每次可以计算出水平方向的遮挡面积，同时还需要减去竖直方向的遮挡面积 min(grid[i][j],grid[i-1][j])x2，这样才能算出正确的表面积
class Solution {
public:
    int surfaceArea(vector<vector<int>>& grid) {
        int n = grid.size();
        int res{0};
        for (int i{0}; i < n; ++i) {
            for (int j{0}; j < n; ++j) {
                if (grid[i][j] > 0) res += 4*grid[i][j] + 2;
                if (i > 0) res -= min(grid[i][j], grid[i-1][j]) * 2;
                if (j > 0) res -= min(grid[i][j], grid[i][j-1]) * 2;
            }
        }
        return res;
    }
};